#include "GRO_Gui.h"
#include <iostream>
#include "SDL_image.h"
#include <unistd.h>
using namespace std;

#include "GRO_Backend_Sprig.h"
#include "GRO_Font_NFont.h"
#include "GRO_XPTheme.h"

SDL_Surface* screen;
Uint8* keystates;

#include "sprig.h"
#include "NFont.h"
#include "SDL_ttf.h"



int moo(int i)
{
    cout << "Moo: " << i << endl;
    return i;
}

void cow(int i)
{
    cout << "Cow: " << i << endl;
    return;
}

void setSelectedFile(string* str, GRO::FileBrowser* browser)
{
    if(str == NULL || browser == NULL)
        return;
    *str = browser->getResult();
}

void setBool(bool* b, bool value)
{
    if(b != NULL)
        *b = value;
}

int& getMX(int& mx)
{
    return mx;
}

void start()
{
    using namespace GRO;
    SDL_Surface* BG = IMG_Load("../GUI_Screens/WindowsXP.jpg");
    
    
 
    EnableUnicode();
    KeyRepeat();
    
    
    Gui& gui = Gui::instance();
    gui.init(screen->format, screen->w, screen->h);
    
    //gui->theme = createXPTheme();
    
    SDL_Surface* pointer0 = IMG_Load("../images/pointer.png");
    SDL_Surface* pointer1 = IMG_Load("../images/pointer1.png");
    SDL_Surface* pointer2 = IMG_Load("../images/pointer2.png");
    
    static_cast<PointerCursor*>(gui.cursors.front())->image = pointer0;
    SDL_ShowCursor(0);
    //gui->cursors.clear();
    //static_cast<PointerCursor*>(gui->cursors.front())->image = IMG_Load("pointer.png");
    KeyboardSettings* keySettings = new KeyboardSettings;
    PointerCursor* keyboardCursor = new PointerCursor(keySettings, pointer1);
    keyboardCursor->gui = &gui;
    gui.cursors.push_back(keyboardCursor);
    
    SDL_JoystickEventState(SDL_ENABLE);
    JoystickSettings* joySettings = new JoystickSettings(SDL_JoystickOpen(0));
    PointerCursor* joystickCursor = new PointerCursor(joySettings, pointer2);
    joystickCursor->gui = &gui;
    gui.cursors.push_back(joystickCursor);
    
    /*joystickCursor = new PointerCursor(new JoystickSettings(SDL_JoystickOpen(1)), IMG_Load("pointer2.png"));
    joystickCursor->gui = gui;
    gui->cursors.push_back(joystickCursor);
    */
    
    
    SPG_PushThickness(1);
    
    NFont f1;
    TTF_Font* ttf = TTF_OpenFont("../fonts/FreeSans.ttf", 14);
    SDL_Color fgColor = {0, 0, 0, SDL_ALPHA_OPAQUE};
    f1.load(ttf, fgColor);
    //f1.setFont(screen, IMG_Load("../fonts/BlackTahoma16.png"), 1);
    f1.setDest(screen);
    
    NFont whiteFont;
    whiteFont.load(screen, NFont::verticalGradient(NFont::copySurface(f1.getSurface()), 0xffffff, 0x999999, 0));
    
    NFont boldFont;
    TTF_SetFontStyle(ttf, TTF_STYLE_BOLD);
    //boldFont.loadTTF(ttf, fgColor);
    boldFont.load(screen, NFont::verticalGradient(NFont::copySurface(f1.getSurface()), 0xffffff, 0x999999, 0));
    NFont redFont;
    redFont.load(screen, NFont::verticalGradient(NFont::copySurface(f1.getSurface()), 0xffffff, 0x999999, 0));
    
    
    
    
    
    TTF_CloseFont(ttf);
    
    
    
    
    
    
    GRO_Font* font1 = new GRO_Font_NFont(&f1);
    GRO_Font* font2 = new GRO_Font_NFont(&whiteFont);
    GRO_Font* font3 = new GRO_Font_NFont(&boldFont);
    GRO_Font* font4 = new GRO_Font_NFont(&redFont);
    
    gui.theme->add(TEXT, font4, THEME_FONT2);
    
    Window* window = new Window(30, 30, 400, 300, "My Window", font2);
    
    gui.add(window);
    
    Panel* panel = window;
    panel->setGridSize(4, 4);
    
    Widget* widget = new Text("Foods I Like:", font1);
    panel->set(0,0,widget);
    
     

    widget = new Checkbox(20, 20, true);
    panel->set(1,0,widget);
 

 
    widget = new Text(" Pizza", font1);
    panel->set(1,1,widget);
    

    
    widget = new Checkbox(20, 20, false);
    //widget->setFrame(XPCBFrame);
    //widget->setBox(XPCBBox);
    panel->set(2,0,widget);

    widget = new Text("Broccoli", font1);
    panel->set(2,1,widget);

    //bool blah = 0;
    //widget = new Checkbox(40, 40, &blah);
    //panel->set(2,3,widget);

    
    /*Group* group = new Group(180, 80);
    group->setGridSize(3, 2);
    panel->set(4, 0, group);
    
    widget = new Text("My grroop", &f1);
    group->add(widget);
    
    widget = new Checkbox(40, 20, true);
    group->add(widget);*/
    
    
    
    
    /*widget = new MenuItem(gui, "Open/Close\n Menu", &f1);
    widget->area.w = 100;
    widget->area.h = 40;
    Panel* menu = new Panel(0, 0, 100, 400);
    menu->folded = 1;
    
    static_cast<MenuItem*>(widget)->callback = MenuCallback;
    static_cast<MenuItem*>(widget)->callbackWidget = menu;
    
    gui->add(menu);
    
    panel->set(3, 0, widget);*/
    
    
    // Editable text
    Group* group = new Group(200, 200);
    group->name = "G1";
    
    widget = new ScrollBar(15, group->area.h - 20, 15, 10, 15, 15, DOWN);

    widget->setDock(DOCK_UP_RIGHT);
    widget->padding.up = 10;
    group->pin(widget);
    group->setScroll(static_cast<ScrollBar*>(widget), DOWN);
    
    widget = new Text("I like this one because:\n", font1);
    dynamic_cast<Text*>(widget)->editable = 1;
    dynamic_cast<Text*>(widget)->textMax = 1000;
    widget->area.w = 170;
    widget->area.h = 400;
    
    panel->set(3, 1, group);
    group->set(0, 0, widget);
    panel->fitContents();
    
    
    
    
    
    panel = new Panel(300, 400, 200, 200);
    

    //panel->setFrame(XPFrame);
    //panel->setBox(XPBox);
    gui.add(panel);
    
    widget = new Checkbox(40, 40, true);
    
    panel->set(0,0,widget);
    
    widget = new Button(40, 40);
    
    Panel* panel2 = NULL;
    ColorPickerSimple* colorPicker = new ColorPickerSimple(300, 200, 350, 150, font1, &gui);
    colorPicker->name = "ColorPicker";
    //Panel* panel2 = ColorPicker(gui, 300, 200, 400, 300, &f1);
    colorPicker->setFolded(1);
    gui.add(colorPicker);
    //Panel* myPanel = colorPicker;
    
    widget->onClick.connect<Panel, void>(colorPicker, &Panel::open);
    widget->setBox(new RoundedBoxPainter(0xaa88ee, 10), 1); // This should be a diagonal gradient to look nice
    //widget->setBox(new LinearGradientBoxPainter(DOWN, new GradientRamp(0xaabbb0, 0x77bb99), 1), 1); // This should be a diagonal gradient to look nice
    widget->setFrame(new RoundedFramePainter(2, 1, 10, 0), 1);
    static_cast<Button*>(widget)->frameDown = new RoundedFramePainter(2, 1, 10, 1);
    // lower
    //gui->add(panel2);
    
    
    panel->set(1,0,widget);
    
    
    FileBrowser* fileBrowser = new FileBrowser(200, 200, 350, 200, font1, font3, "/home/jonny");
    fileBrowser->name = "File Browser";
    fileBrowser->setFolded(1);
    fileBrowser->refresh();
    
    string selectedFile = "No file selected";
    //Signal2<void, string*, FileBrowser*> sigSelectFile(setSelectedFile);
    //sigSelectFile.setArgs(&selectedFile, fileBrowser);
    //fileBrowser->setDoneSignal(&sigSelectFile);
	//fileBrowser->doneEmitter.connect(Signal2<string*>(fileBrowser, getSelectedFile, &selectedFile));
    
    gui.add(fileBrowser);
    
    widget = new Button(50, 30);
    
    widget->onClick.connect<Panel, void>(fileBrowser, &Panel::open);
    
    panel->set(0, 1, widget);
    
    Text* fileText = new Text("No file selected", font1);
    fileText->link(&selectedFile);
    
    panel->set(0, 2, fileText);
    
    
    widget = new Slider(100, 60);
    widget->name = "S1";
    static_cast<Slider*>(widget)->direction = LEFT;
    
    panel->set(2, 0, widget);
    widget = new Slider(60, 100);
    widget->name = "S2";
    static_cast<Slider*>(widget)->direction = UP;
    
    panel->set(2, 1, widget);
    
    widget = new Button(100, 60, new Text("This is a\nborderless\nbutton", font1));
    static_cast<Button*>(widget)->text->textType = THEME_FONT2;
    
    panel->set(1, 1, widget);
    
    
    panel = Dialog(&gui, 370, 370, 200, 100, "This is\na pop-up message.", font1, "OK", font1);
    panel->setFolded(1);
    panel->grabInput = 1;
    
    widget->onClick.connect<Panel, void>(panel, &Panel::open);
    widget->setFrame(NULL);
    
    
    
    
    
    
    panel = new Panel(400, 5, 300, 300);
    
    group = new Group(200, 100);
    group->name = "G2";
    Slider* slider = new Slider(100, 40);
    widget->name = "S3";
    Text* text = new Text("100", font1);
    int value = 0;
    text->link(&value);
    gui.add(panel);
    panel->set(0,0,group);
    group->set(0, 0, text);
    group->set(0, 1, slider);
    
    slider->link(&value);
    
    
    widget = new ScrollBar(15, group->area.h - 20, 15, 10, 15, 15, DOWN);

    widget->setDock(DOCK_UP_RIGHT);
    widget->padding.up = 10;
    group->pin(widget);
    group->setScroll(static_cast<ScrollBar*>(widget), DOWN);
    
    Group* group2 = new Group(200, 100);
    group2->name = "G3";
    
    widget = new Spinner(50, 70);
    static_cast<Spinner*>(widget)->direction = DOWN;
    static_cast<Spinner*>(widget)->max = 4000;
    static_cast<Spinner*>(widget)->min = 351;
    
    text = new Text("4000", font1);
    text->link(&(static_cast<Spinner*>(widget)->value));
    
    group->set(1, 0, group2);
    group2->set(0,0,text);
    group2->set(0,1,widget);
    
    SDL_Surface* ballImage = IMG_Load("../images/Ball.png");
    widget = new Image(ballImage);
    panel->set(1,0,widget);
    
    ProgressBar* progressBar = new ProgressBar;
    progressBar->setProgress(0.65f);
    
    GradientRamp* gc2 = new GradientRamp;
    // Blue gradient
    /*gc2->first.color = 0xaaaaaa;
    gc2->add(GradientPoint(0.2f, 0x9090aa));
    gc2->add(GradientPoint(0.5f, 0x555588));
    gc2->add(GradientPoint(0.65f, 0x333355));
    gc2->last.color = 0x9090aa;*/
    // Gold metallic gradient
    gc2->first.color = 0x888800;
    gc2->add(GradientPoint(0.25f, 0xffffff));
    gc2->add(GradientPoint(0.5f, 0xbbbbbb));
    gc2->add(GradientPoint(0.6f, 0x888800));
    gc2->add(GradientPoint(0.75f, 0xaaaa55));
    gc2->last.color = 0xddddaa;
    
    LinearGradientBoxPainter* bp = new LinearGradientBoxPainter;
    bp->gradient = gc2;
    //bp->direction = RIGHT;
    bp->direction = DOWN;
    //progressBar->centerBox = true;
    //progressBar->centerFrame = true;
    //panel->setBox(bp);
    
    panel->set(1,1,progressBar);
    
    progressBar->setFrame(new FramePainter, true);
    progressBar->progressBox = bp;
    progressBar->progressFrame = NULL;
    //progressBar->boxPadding = 1;
    //progressBar->framePadding = 1;
    
    
    
    
    ProgressBar* progressBar2 = new ProgressBar;
    progressBar2->setProgress(0.65f);
    progressBar2->setFrame(new FramePainter, true);
    
    SDL_Surface* lavaImage = IMG_Load("../images/lava.png");
    
    ImageBoxPainter* ibp = new ImageBoxPainter(lavaImage, 0, 0, false, false, false);
    
    
    panel->set(1,2,progressBar2);
    progressBar2->progressBox = ibp;
    
    
    
    
    
    
    RadioSystem* radioSystem = new RadioSystem;
    
    Radio* radio = new Radio;
    panel->set(1, 3, radio);
    
    radio = new Radio(7, 7);
    radioSystem->add(radio);
    panel->set(2, 0, radio);
    
    radio = new Radio(12, 12);
    radioSystem->add(radio);
    panel->set(2, 1, radio);
    
    radio = new Radio(17, 17);
    radioSystem->add(radio);
    panel->set(2, 2, radio);
    
    radio = new Radio(22, 22);
    radioSystem->add(radio);
    panel->set(2, 3, radio);
    
    Color* color = new Color(40, 20);
    color->color = 0x0055ff;
    panel->set(2, 4, color);
    
    Gradient* gradient = new Gradient(60, 60);
    gradient->color1 = 0x0055ff;
    gradient->color2 = 0xff0000;
    gradient->gradient = new GradientRamp;
    gradient->direction = UP;
    panel->set(2, 5, gradient);
    
    
    widget = new ScrollBar(panel->area.w - 30 - 10, 15, 30, 15, 15, 15, RIGHT);
    //widget->grabMouseWheelFocus = 0;

    //panel->set(2,3,widget);
    widget->setDock(DOCK_DOWN_LEFT);
    widget->padding.left = 10;
    panel->pin(widget);
    panel->setScroll(static_cast<ScrollBar*>(widget), RIGHT);
    
    widget = new ScrollBar(15, panel->area.h - 30 - 10, 15, 30, 15, 15, DOWN);

    //panel->set(2,4,widget);
    widget->setDock(DOCK_UP_RIGHT);
    widget->padding.up = 10;
    panel->pin(widget);
    panel->setScroll(static_cast<ScrollBar*>(widget), DOWN);
    
    SelectTextSystem* ssystem = new SelectTextSystem;
    
    SelectText* stext = new SelectText(&gui, "Select me", font1);
    ssystem->add(stext);
    
    panel->set(3, 0, stext);
    
    ListBox* listBox = new ListBox(100, 100);
    
    listBox->add(new SelectText(&gui, "Select1", font1));
    listBox->add(new SelectText(&gui, "Select2", font1));
    listBox->insert(new SelectText(&gui, "Select3", font1), 1);
    
    SelectText* extra = new SelectText(&gui, "Select4", font1);
    listBox->add(extra);
    //listBox->add(new SelectText(gui, "Select5", font1));
    listBox->system.numChooseable = 2;
    
    panel->set(3, 1, listBox);
    
    gui.add(panel2);
    
    
    
    panel = new Panel(5, 400, 200, 200);
    panel->setGridSize(4, 4);
    panel->displacement.up = 30;
    
    widget = new Text("Num1", font1);
    panel->set(1, 2, widget);
    widget = new Text("Num2", font1);
    panel->add(widget);
    widget = new Text("Num3", font1);
    panel->add(widget);
    widget = new Text("Num4", font1);
    panel->add(widget);
    widget = new Text("Num5", font1);
    panel->add(widget);
    
    widget = new Expander(40, 40, true);
    panel->add(widget);
    widget = new Separator(60, 10);
    panel->add(widget);
    widget = new Separator(10, 60, 0xff0000, DOWN);
    panel->add(widget);
    
    widget = new Text("Num6", font1);
    panel->add(widget);
    widget = new Text("Num7", font1);
    panel->add(widget);
    widget = new Text("Num8", font1);
    panel->add(widget);
    widget = new Text("Num9", font1);
    panel->add(widget);
    widget = new Text("Num10", font1);
    panel->add(widget);
    widget = new Text("Num11", font1);
    panel->add(widget);
    
    widget = new Mover(40, 40, panel);
    panel->add(widget);
    widget = new Resizer(40, 40, panel);
    panel->add(widget);
    
    /*GradientRamp gc;
    gc.add(GradientPoint(0.3f, 0xff0000));
    gc.add(GradientPoint(0.8f, 0x004400));
    gc.add(GradientPoint(0.4f, 0x000077));
    
    
    gradient = new Gradient(60, 60, &gc);
    gradient->direction = UP;
    panel->set(0, 0, gradient);
    gradient = new Gradient(60, 60, &gc);
    gradient->direction = DOWN;
    panel->set(0, 1, gradient);
    gradient = new Gradient(60, 60, &gc);
    gradient->direction = LEFT;
    panel->set(1, 0, gradient);
    gradient = new Gradient(60, 60, &gc);
    gradient->direction = RIGHT;
    panel->set(1, 1, gradient);
    */
    gui.add(panel);
    
    //gui->applyTheme(createXPTheme());
    
    SPG_EnableDirty(1);
    SPG_DirtyInit(64);
    
    
    
    SDL_FillRect(screen, NULL, 0x7171C6);
    SDL_Flip(screen);
    Uint32 frametime;
    
    float targetFps = 60;
    float waitTime = 1000.0f / targetFps;
    
    int mx = 0, my = 0;
    
    bool done = 0;
    
    // Add QUIT shortcut
    //Signal1<void, bool*>* quitSignal = new Signal1<void, bool*>(done_callback);
    //quitSignal->setArg1(&done);
    Shortcut* shortcut = new Shortcut(KMOD_CTRL, SDLK_q);
    shortcut->onExecute.connect<void, bool*, bool>(setBool, &done, true);
    gui.addShortcut(shortcut);
    
    
    SDL_Event event;
    int frameStart;
    while (!done)
    {
        frameStart = SDL_GetTicks();
        SDL_GetMouseState(&mx, &my);
        
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                done = 1;
            
            if(gui.event(event) != NULL)
                continue;
            

            if (event.type == SDL_KEYDOWN)
            {
                //if (event.key.keysym.sym == SDLK_q)
                //    done = 1;
                if(event.key.keysym.sym == SDLK_1)
                    listBox->add(extra);
                if(event.key.keysym.sym == SDLK_2)
                    listBox->remove(extra);
                /*if(event.key.keysym.sym == SDLK_a)
                {
                    if(Default_DarkShadowBoxPainter.boxAlpha == SDL_ALPHA_OPAQUE)
                        Default_DarkShadowBoxPainter.boxAlpha = 127;
                    else
                        Default_DarkShadowBoxPainter.boxAlpha = SDL_ALPHA_OPAQUE;
                }
                if(event.key.keysym.sym == SDLK_s)
                {
                    if(Default_LightBoxPainter.boxAlpha == SDL_ALPHA_OPAQUE)
                        Default_LightBoxPainter.boxAlpha = 127;
                    else
                        Default_LightBoxPainter.boxAlpha = SDL_ALPHA_OPAQUE;
                }
                if(event.key.keysym.sym == SDLK_d)
                {
                    if(Default_DarkBoxPainter.boxAlpha == SDL_ALPHA_OPAQUE)
                        Default_DarkBoxPainter.boxAlpha = 127;
                    else
                        Default_DarkBoxPainter.boxAlpha = SDL_ALPHA_OPAQUE;
                }*/
            }
        }
        
        /*if(keystates[SDLK_UP])
        {
            if(myPanel->getBox() != NULL)
                myPanel->getBox()->dropShadowY-=2;
        }
        if(keystates[SDLK_DOWN])
        {
            if(myPanel->getBox() != NULL)
                myPanel->getBox()->dropShadowY+=2;
        }
        if(keystates[SDLK_LEFT])
        {
            if(myPanel->getBox() != NULL)
                myPanel->getBox()->dropShadowX-=2;
        }
        if(keystates[SDLK_RIGHT])
        {
            if(myPanel->getBox() != NULL)
                myPanel->getBox()->dropShadowX+=2;
        }*/
        
        SPG_Draw(BG,screen, 0,0);
        
        progressBar->increment(0.01f);
        progressBar2->increment(0.005f);
        gui.update();
        
        gui.draw();

        //f1.draw(0, 0, "(%d, %d)", mx, my);
        SPG_EnableDirty(0);
        
        if(SPG_DirtyEnabled())
        {
            SPG_DirtyTable* table = SPG_DirtyUpdate(screen);
            
            for(int i = 0; i < table->count; ++i)
            {
                SDL_FillRect(screen, &(table->rects[i]), 0x7171C6);
            }
            
            SPG_DirtySwap();
        }
        else
        {
            SDL_Flip(screen);
            SDL_FillRect(screen, NULL, 0x7171C6);
        }
        
        frametime = SDL_GetTicks() - frameStart;

        if (SDL_GetTicks() - frameStart < waitTime)
            SDL_Delay((int)(waitTime - frametime));

    }
    
    SDL_FreeSurface(f1.getSurface());
    SDL_FreeSurface(whiteFont.getSurface());
    SDL_FreeSurface(boldFont.getSurface());
    SDL_FreeSurface(redFont.getSurface());
    
    delete font1;
    delete font2;
    delete font3;
    delete font4;
    
    // Need to save the painters somewhere...  Not in the gui, since I want to free them more often...
    delete ibp;
    
    // Need better policy for memory management of images in widgets
    
    SDL_FreeSurface(ballImage);
    SDL_FreeSurface(pointer0);
    SDL_FreeSurface(pointer1);
    SDL_FreeSurface(pointer2);
    SDL_FreeSurface(lavaImage);
    
    // Need to save the pointers somewhere
    delete joySettings;
    delete joystickCursor;
    delete keySettings;
    delete keyboardCursor;
    
    // Systems are too flexible.
    delete ssystem;
}







int main(int argc, char* argv[])
{
    cout << argv[0] << endl;
    char buffer[2000];
    char* cwd = getcwd(buffer, 2000);
    cwd = NULL;
    cout << buffer << endl;
    string path = argv[0];
    path = path.substr(0, path.find_last_of('/'));
    path += '/';
    int res = chdir(path.c_str());
    res = 0;
    
    char buff[] = "SDL_VIDEO_CENTERED=center";
    
    SDL_putenv(buff);
    
    screen = SPG_InitSDL(800, 600, 32, SDL_INIT_VIDEO | SDL_INIT_JOYSTICK, SDL_SWSURFACE);
    if(screen == NULL)
        return 0;
    int numJoy = SDL_NumJoysticks();
    if(numJoy > 0)
    {
        printf("%i joysticks were found.\n\n", numJoy);
        printf("The names of the joysticks are:\n");

        for( int i=0; i < numJoy; i++ )
        {
            printf("    %s\n", SDL_JoystickName(i));
        }
    }
    
    SDL_WM_SetCaption("Gui Test", NULL);
    
    keystates = SDL_GetKeyState(NULL);
    
    TTF_Init();
    
    GRO::GRO_SetRenderer(new GRO::Renderer_Sprig(screen));
    
    srand(time(NULL));
    start();
    
    GRO::Gui::instance().deleteChildren();
    
    GRO::GRO_FreeRenderer();
    
    SDL_Quit();
    return 0;
}
